#include <iostream>
#include <boost/thread.hpp>

#include <gtest/gtest.h>

#include "url.h"
#include "server.h"

using namespace std;
using namespace boost;
using namespace crawler::server;

TEST(ServerTest, Url)
{
  string urls[] = {
    "http://user:pwd@example.com:80/a/c/index.php?a=3&b=4#ref",
    "http://user@example.com:88/a/c/index.php?a=3&b=4",
    "http://example.com/a/c/index.php",
    "http://example.com",
    "http://example.com/",
    "http://example.com/.././a/c/.././index.php",
    "http://example.com?index.php",
    "http://example.com#ref",
    "http://example.com#?index.php",
    "http://example.com?a=3#ref",
    "http://example.com/a/c/?#",
  };
  for (size_t i=0; i<sizeof(urls)/sizeof(urls[0]); ++i) {
    string u = urls[i];
    Url url(u);
    cout << "url:" << u << endl;
    cout << "valid:" << url.IsValid() << endl;
    cout << "scheme:" << url.GetScheme() << endl;
    cout << "user:" << url.GetUser() << endl;
    cout << "pwd:" << url.GetPassword() << endl;
    cout << "host:" << url.GetHost() << endl;
    cout << "port:" << url.GetPort() << endl;
    cout << "path:" << url.GetPath() << endl;
    cout << "query:" << url.GetQuery() << endl;
    cout << "ref:" << url.GetRef() << endl;
    cout << "directory:" << url.GetDirectory() << endl;
    cout << "depth:" << url.GetDepth() << endl;
    cout << "file:" << url.GetFile() << endl;
    cout << "suffix:" << url.GetFileSuffix() << endl;
    cout << "normalize:" << url.GetNormalized() << endl;
    cout << "href_link:/abc/index.html -> " << url.GetHrefLink("/abc/index.html") << endl;
    cout << "href_link:a/b/../index -> " << url.GetHrefLink("a/b/../index") << endl;
  }
}
TEST(ServerTest, Store)
{
  string db_path = "test_store_db";
  Store store(db_path);

  Store::PageIterator empty_it = store.Begin();
  EXPECT_EQ(empty_it, store.End());

  Page p1;
  p1.__set_url("http://test/page1");
  Link l1;
  l1.__set_url("http://test/l1");
  store.StorePage(p1);
  store.StoreLink(l1);

  Page p1_r;
  store.GetPage(p1.url, p1_r);
  EXPECT_EQ(p1.url, p1_r.url);
  EXPECT_EQ(p1.content, p1_r.content);

  Store::PageIterator it = store.Begin();
  EXPECT_EQ((*it).url, l1.url);
  ++it;
  EXPECT_EQ(it->url, p1.url);
  ++it;
  EXPECT_EQ(it, store.End());

  system(("rm -fr " + db_path).c_str());
}
TEST(ServerTest, Server)
{
  int argc = 3;
  const char *argv[] = {"test", "-s" , "test_store_db"};
  Config config(argc, (char **)argv);

  Store store(config.store_db_path());
  CrawlerServerHandler handler(&store, &config);

  for (size_t i=0; i<CrawlerServerHandler::kPoolSize; ++i) {
    ostringstream oss;
    if (i % 2 == 0) {
      oss << "http://test/a/" << setw(10) << setfill('0') << i;
    } else {
      oss << "http://test/b/c/" << setw(10) << setfill('0') << i;
    }
    Link l;
    l.__set_url(oss.str());
    store.StoreLink(l);
  }

  string url;
  handler.GetDownloadUrl(url);
  for (size_t i=0; i<CrawlerServerHandler::kPoolSize/2; ++i) {
    handler.GetDownloadUrl(url);
    EXPECT_TRUE(url.find("http://test/a/") == 0);
  }
  for (size_t i=0; i<CrawlerServerHandler::kPoolSize/2-1; ++i) {
    handler.GetDownloadUrl(url);
    EXPECT_TRUE(url.find("http://test/b/c/") == 0);
  }

  system(("rm -fr " + config.store_db_path()).c_str());
}

